Infer paths as well as names for binaries
authorSehny <msehnout@users.noreply.github.com>
Tue, 27 Jun 2017 17:51:56 +0000 (19:51 +0200)
committerSehny <msehnout@users.noreply.github.com>
Tue, 27 Jun 2017 17:51:56 +0000 (19:51 +0200)
src/cargo/util/toml.rs
tests/build.rs

index 9cf1f5386c6f9e63aacda4c64655c2a4d482e72b..b70b102f72268324baf8f9692d3fb5f7a410fc5f 100644 (file)
@@ -83,13 +83,12 @@ fn try_add_mains_from_dirs(files: &mut Vec<PathBuf>, root: PathBuf) {
             // Filter only directories
             .filter(|i| {
                 i.file_type().map(|f| f.is_dir()).unwrap_or(false)
-                // Convert DirEntry into PathBuf and append "main.rs"
+            // Convert DirEntry into PathBuf and append "main.rs"
             }).map(|i| {
-            i.path().join("main.rs")
+                i.path().join("main.rs")
             // Filter only directories where main.rs is present
-        }).filter(|f| {
-            f.as_path()
-                .exists()
+            }).filter(|f| {
+                f.as_path().exists()
         }).collect();
         files.extend(new);
     }
@@ -532,7 +531,12 @@ fn inferred_bin_targets(name: &str, layout: &Layout) -> Vec<TomlTarget> {
                     // if the path ends with main.rs it is probably a directory, but it can also be
                     // a file directly inside src/bin
                     if parent.ends_with("src/bin") {
-                        bin.file_stem().and_then(|s| s.to_str()).map(|f| f.to_string())
+                        // This would always return name "main"
+                        // Fixme: Is this what we want? based on what @matklad said, I don't think so
+                        // bin.file_stem().and_then(|s| s.to_str()).map(|f| f.to_string())
+
+                        // This seems to be the right solution based on the inferred_bin_paths function
+                        Some(name.to_string())
                     } else {
                         parent.file_stem().and_then(|s| s.to_str()).map(|f| f.to_string())
                     }
@@ -1481,7 +1485,7 @@ fn inferred_bin_path(bin: &TomlBinTarget,
                      package_root: &Path,
                      bin_len: usize) -> PathBuf {
     // here we have a single bin, so it may be located in src/main.rs, src/foo.rs,
-    // srb/bin/foo.rs or src/bin/main.rs
+    // src/bin/foo.rs, src/bin/foo/main.rs or src/bin/main.rs
     if bin_len == 1 {
         let path = Path::new("src").join(&format!("main.rs"));
         if package_root.join(&path).exists() {
@@ -1500,6 +1504,12 @@ fn inferred_bin_path(bin: &TomlBinTarget,
             return path.to_path_buf()
         }
 
+        // check for the case where src/bin/foo/main.rs is present
+        let path = Path::new("src").join("bin").join(bin.name()).join(&format!("main.rs"));
+        if package_root.join(&path).exists() {
+            return path.to_path_buf()
+        }
+
         return Path::new("src").join("bin").join(&format!("main.rs")).to_path_buf()
     }
 
@@ -1509,6 +1519,12 @@ fn inferred_bin_path(bin: &TomlBinTarget,
         return path.to_path_buf()
     }
 
+    // we can also have src/bin/foo/main.rs, but the former one is preferred
+    let path = Path::new("src").join("bin").join(bin.name()).join(&format!("main.rs"));
+    if package_root.join(&path).exists() {
+        return path.to_path_buf()
+    }
+
     if !has_lib {
         let path = Path::new("src").join(&format!("{}.rs", bin.name()));
         if package_root.join(&path).exists() {
index 096927a6b6ecb6758ae7d9614c341003475c65dc..bbc1ca1b167cf339b1f1e8797f174e35aaeece68 100644 (file)
@@ -3285,7 +3285,6 @@ fn dirs_in_bin_dir_with_main_rs() {
         .file("src/main.rs", "fn main() {}")
         .file("src/bin/bar.rs", "fn main() {}")
         .file("src/bin/bar2.rs", "fn main() {}")
-        .file("src/bin/main.rs", "fn main() {}")
         .file("src/bin/bar3/main.rs", "fn main() {}")
         .file("src/bin/bar4/main.rs", "fn main() {}");
 
@@ -3295,5 +3294,41 @@ fn dirs_in_bin_dir_with_main_rs() {
     assert_that(&p.bin("bar2"), existing_file());
     assert_that(&p.bin("bar3"), existing_file());
     assert_that(&p.bin("bar4"), existing_file());
-    assert_that(&p.bin("main"), existing_file());
+}
+
+#[test]
+fn dir_and_file_with_same_name_in_bin() {
+    // this should fail, because we have two binaries with the same name
+    let p = project("bar")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "bar"
+            version = "0.1.0"
+            authors = []
+        "#)
+        .file("src/main.rs", "fn main() {}")
+        .file("src/bin/foo.rs", "fn main() {}")
+        .file("src/bin/foo/main.rs", "fn main() {}");
+
+    // TODO: This should output the error from toml.rs:756
+    assert_that(p.cargo_process("build"), execs().with_status(101));
+}
+
+#[test]
+fn inferred_path_in_src_bin_foo() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+        [package]
+        name = "foo"
+        version = "0.1.0"
+        authors = []
+
+        [[bin]]
+        name = "bar"
+        # Note, no `path` key!
+        "#)
+        .file("src/bin/bar/main.rs", "fn main() {}");
+
+    assert_that(p.cargo_process("build"), execs().with_status(0));
+    assert_that(&p.bin("bar"), existing_file());
 }